package br.com.felinelayer.client.clientSwing;

import br.com.felinelayer.common.Message;
import br.com.felinelayer.common.Protocol;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.JFrame;

/**
 *
 */
public abstract class ComponentSwing<T extends br.com.felinelayer.client.IComponent,
         V extends java.awt.Component>
        extends br.com.felinelayer.client.Component<T> implements FocusListener {
    
    protected abstract void doInitialize();
    
    @Override
    public void initialize() {
        doInitialize();
    }
    
    protected int getDefaultHeight() {
        return HEIGHT_DEFAULT;
    }
    
    protected int getDefaultWidth() {
        return 100;
    }
    
    protected final <K extends java.awt.Component> V initializeComponente(K jcomponent) {
        Dimension s = jcomponent.getSize();
        s.height = getDefaultHeight();
        s.width = getDefaultWidth();
        jcomponent.setSize( s );
        setObject( jcomponent );
        return (V) jcomponent;
    }

    public static final int HEIGHT_DEFAULT = 24;
    public int id = 0;
    private Object object;
    private String previosText = "";

    @Override
    public T setId( int id ) {
        this.id = id;
        return (T) this;
    }

    @Override
    public T setVisible( boolean visible ) {
        if ( getObject() instanceof JComponent )
            ( (JComponent) getObject() ).setVisible( visible );
        if ( getObject() instanceof JFrame )
            ( (JFrame) getObject() ).setVisible( visible );
        return (T) this;
    }

    @Override
    public T setWidht( int width ) {
        Dimension d = getDimension();
        d.width = width;
        setDimension( d );
        return (T) this;
    }

    @Override
    public T setHeight( int height ) {
        Dimension d = getDimension();
        d.height = height;
        setDimension( d );
        return (T) this;
    }

    @Override
    public abstract T setText( String text );

    @Override
    public abstract String getText();

    @Override
    public Object getObject() {
        return object;
    }

    public T setObject( Object object ) {
        this.object = object;
        if ( object instanceof JComponent )
            ( (JComponent) getObject() ).addFocusListener( this );
        return (T) this;
    }

    public Rectangle getBounds() {
        if ( getObject() instanceof JComponent )
            return ( (JComponent) getObject() ).getBounds();
        if ( getObject() instanceof JFrame )
            return ( (JFrame) getObject() ).getBounds();
        return null;
    }

    public T setBounds( Rectangle rectangle ) {
        if ( getObject() instanceof JComponent )
            ( (JComponent) getObject() ).setBounds( rectangle );
        if ( getObject() instanceof JFrame )
            ( (JFrame) getObject() ).setBounds( rectangle );
        return (T) this;
    }

    public Dimension getDimension() {
        if ( getObject() instanceof JComponent )
            return ( (JComponent) getObject() ).getSize();
        if ( getObject() instanceof JFrame )
            return ( (JFrame) getObject() ).getSize();
        return null;
    }

    public T setDimension( Dimension rectangle ) {
        if ( getObject() instanceof JComponent )
            ( (JComponent) getObject() ).setSize( rectangle );
        if ( getObject() instanceof JFrame )
            ( (JFrame) getObject() ).setSize( rectangle );
        return (T) this;
    }

    public int getHeight() {
        return (int) getBounds().getHeight();
    }

    @Override
    public T setTop( int top ) {
        Rectangle b = getBounds();
        b.y = top;
        setBounds( b );
        return (T) this;
    }

    @Override
    public T setLeft( int left ) {
        Rectangle b = getBounds();
        b.x = left;
        setBounds( b );
        return (T) this;
    }

    protected Message createEvent( String name ) throws Exception {
        return getClient().createEvent( this, name );
    }

    protected void fireEvent( String name ) throws Exception {
        getClient().sendEvent( this, name );
    }

    protected T fireEvent( Message message ) {
        getClient().sendMessage( message );
        return (T) this;
    }

    protected Message fireInquireEvent( Message message ) {
        return getClient().inquireMessage( message );
    }

    @Override
    protected void doChangeProperty( Message message ) {
    }

    @Override
    public void messageReceived( Message message ) {
    }

    /**
     * Invoked when a component gains the keyboard focus.
     */
    @Override
    public void focusGained( FocusEvent e ) {
        try {
            previosText = getText();
            fireEvent( Protocol.EVENT_FOCUS_ENTER );
        } catch (Exception ex) {
            Logger.getLogger(ComponentSwing.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Invoked when a component loses the keyboard focus.
     */
    @Override
    public void focusLost( FocusEvent e ) {
        try {
            Message m = createEvent( Protocol.EVENT_FOCUS_EXIT );
            String currentText = getText();
            if ( !previosText.equalsIgnoreCase( getText() ) )
                m.setValueByName( Protocol.PROPERTY_NAME_TEXT, currentText );
            fireEvent( m );
        } catch (Exception ex) {
            Logger.getLogger(ComponentSwing.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    protected void doDestroy() {
        if ( object instanceof JComponent )
            ( (JComponent) getObject() ).getParent().remove( (JComponent) getObject() );
    }
}
